"""
python nd_bird_pyswarm_copy.py
"""

import numpy as np
from pso_edit import pso
import read_4_json as r4j

data_warehouse = r4j.load_warehouse_data()
data_category_inventory = r4j.load_average_inventory_data()
data_category_sales = r4j.load_average_sales_data()
data_category_assotication = r4j.load_association_data()
mx_category_association = r4j.create_adjacency_matrix()

NUM_W = r4j.NUM_W
# NUM_W = 10
NUM_C = r4j.NUM_C


flag = False
def test_objective_function(coords):
    global flag  # 声明flag为全局变量
    if not flag:  # 使用 not 更为简洁
        print("coords: ", coords)
        print("type of arg coords: ", type(coords))
        # rounded_coords = np.round(coords).astype(int)
        # print("四舍五入后的数组：", rounded_coords)
        
    flag = True  # 设置flag为True

    # 对任意维度的坐标求和 (平方和)
    return sum(x**2 for x in coords)

# python遍历是左闭右开
# for i in range(1, 10+1):  # range(1, 11) 生成从1到10（不包括11）的数字
#     print(i)



def utilization_score(x):
    if ( x<0 ):
        raise ValueError("你这个传入利用率分数函数里面的x must be non-negative")
    
    if ( 0<=x<=1 ):
        return x*100.0
    if ( x>1 ):
        return 100.0 / x

def cal_4f_fitness(coords):
    rounded_coords = np.round(coords).astype(int)
    # print("四舍五入后的数组：", rounded_coords)
    
    f1 = 0
    f2 = 0
    f3 = 0
    f4 = 0
    
    # -----f1-----
    w_bucket = [0] * (NUM_W)
    for x in rounded_coords:
        # 坐标的每一个分量，四舍五入以后 是多少，仓库id就是多少
        wid = x
        # print("wid = ", wid)
        # print("this x = ", x, end=", ")
        w_bucket[wid] += 1
    
    for i in range(0,NUM_W):
        if ( w_bucket[i] > 0 ):
            # print("给f1加上", data_warehouse[i]['daily_cost'])
            f1 += data_warehouse[i]['daily_cost']
            
    # print("f1 = ", f1)
    
    # -----f2 f3-----
    sum_inventory_all_w = [0] * (NUM_W) 
    sum_sales_all_w = [0] * (NUM_W)          
    
    # for x in rounded_coords:
    for idx, val in enumerate(rounded_coords):
        cid = idx
        wid = val
        sum_inventory_all_w[wid] += data_category_inventory[cid]['average_inventory']
        sum_sales_all_w[wid]     += data_category_sales[cid]['average_sales']

    for i in range(0,NUM_W):
        f2 += utilization_score( sum_inventory_all_w[i] / data_warehouse[i]['max_inventory'] )
        f3 += utilization_score( sum_sales_all_w[i]     / data_warehouse[i]['max_sales']     )
    
    # print("f2 = ", f2)
    # print("f3 = ", f3)
    # -----f4-----
    
    cinw_mx = [[] for _ in range(NUM_W)]
    for idx, val in enumerate(rounded_coords):
        cid = idx
        wid = val
        cinw_mx[wid].append(cid)
        
    for row_index, row in enumerate(cinw_mx):
        # print("row idx={},: {}".format(row_index, row) )
        len_thisw = len(row)
        for i in range(len_thisw):
            for j in range(len_thisw):
                x = row[i]
                y = row[j]
                # print("x = {}, y = {}".format(x, y), end=", ")
                # print("mx[x][y] = ", mx_category_association[x][y])
                f4 += mx_category_association[x][y]
    
    # print("f4 = ", f4)
     
    return f1,f2,f3,f4, f1*f2*f3*f4
    
    
def obj_func(coords):
    _, _, _, _, res = cal_4f_fitness(coords=coords)
    return res


if __name__ == "__main__":
    # pass

    # print("邻接矩阵：")
    # print(mx_category_association)
    # cnt = 0
    # for i in range(mx_category_association.shape[0]):  # 遍历行
    #     for j in range(mx_category_association.shape[1]):  # 遍历列
    #         x = mx_category_association[i][j]
    #         if ( x!=0 ):
    #             print(f"Element at position ({i}, {j}): {x}")
    #             cnt += 1
    
    # print("none zero cnt = ", cnt)
    
    # random_array = np.random.uniform(low=-0.4999999999, high=NUM_W-1+0.4999999999, size=NUM_W)
    # print("random_arr: ", random_array)
    
    # cal_4f_fitness(random_array)

    # 定义搜索空间维度
    dimension = NUM_C  # 指定维度，可以是任意正整数

    # 定义搜索空间
    lower_bounds = [-0.4999999999] * dimension  # 每个维度的下界
    upper_bounds = [NUM_W-1+0.4999999999] * dimension   # 每个维度的上界

    # 调用PSO算法进行优化
    best_position, best_value = pso(
                                    func = test_objective_function,
                                    cal4tfunc = cal_4f_fitness,
                                    # func = obj_func,
                                    lb = lower_bounds, ub = upper_bounds, 
                                    swarmsize=30, maxiter=3000,
                                    # debug=False,
                                    debug=True,
                                )
    
    rounded_best_position = np.round(best_position).astype(int)

    # 输出结果
    # print("最优位置 (coords):", best_position)
    # print("最小值 f(coords):", best_value)